package xmlHandler;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;

import javax.management.modelmbean.XMLParseException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import xmlHandler.jaxbGenerated.Clue;
import xmlHandler.jaxbGenerated.Player;

public class XmlHandler {
	
	private XmlHandler ()
	{
		
	}
	
	private static class XmlHandlerHolder
	{
		private static final XmlHandler INSTANCE = new XmlHandler ();
	}
	
	public static XmlHandler getInstance ()
	{
		return XmlHandlerHolder.INSTANCE;
		
	}
	
	public Clue readFromXml (String sourceFileNameWithPath) throws FileNotFoundException , IllegalArgumentException , JAXBException , XMLParseException
	{
		
		File sourceFile = new File (sourceFileNameWithPath);
				
		if (!sourceFile.exists())
			throw new FileNotFoundException ("Xml file doesn't exist");
		
		if (!sourceFileNameWithPath.endsWith(".xml"))
			throw new IllegalArgumentException("file name doesn't end with \".xml\"");
		
		try
		{
			JAXBContext context = JAXBContext.newInstance(Clue.class.getPackage().getName());
			Unmarshaller unmarshaller = context.createUnmarshaller();
			Clue rootElement = (Clue) unmarshaller.unmarshal(sourceFile);
			
			validateXmlContent (rootElement);
			
			return rootElement;
		}
		catch (JAXBException jaxbException)
		{
			throw new JAXBException("Xml structure is invalid", jaxbException);
		}
		catch (XMLParseException xmlParseException)
		{
			throw xmlParseException;
		}
		catch (Exception exception)
		{
			System.out.println(exception);
			return null;
		}

	}
	
	public void writeToXml (Clue rootElement , String destinationFileNameWithPath)
	{ 
		
		File destinationFile = new File (destinationFileNameWithPath);
		
		try
		{
		       JAXBContext context = JAXBContext.newInstance(rootElement.getClass());

		       Marshaller marshaller = context.createMarshaller();
		       marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
		       
		       marshaller.marshal(rootElement , new FileWriter(destinationFile));
		}
		catch (JAXBException jaxbException)
		{
			
		}
		catch (IOException ioException)
		{
			
		}
		catch (Exception exception)
		{
			
		}
	}
	
	private void validateXmlContent (Clue rootElement) throws XMLParseException
	{
		if (rootElement.getPlayers().getPlayer().size() < 3 || rootElement.getPlayers().getPlayer().size() > 6)
			throw new XMLParseException("The xml file is bad. Valid number of playares is between 3 to 6");
		
		for (int i = 0 ; i < rootElement.getPlayers().getPlayer().size() ; i++)
		{				
			for (int j = 0 ; j < rootElement.getPlayers().getPlayer().size() ; j++)
			{
				if (i != j)
				{
					if (rootElement.getPlayers().getPlayer().get(i).getName().equals(rootElement.getPlayers().getPlayer().get(j).getName()))
						throw new XMLParseException("The xml file is bad. There can't be two players with the same name");
					
					if (rootElement.getPlayers().getPlayer().get(i).getCharacter().value().equals(rootElement.getPlayers().getPlayer().get(j).getCharacter().value()))
						throw new XMLParseException("The xml file is bad. There can't be two of the same character");
				}
			}		
		}
	}
}
